"use strict";

const utils = require("./../utils");
const transformData = require("./transformData");
const isCancel = require("../cancel/isCancel");
const defaults = require("../defaults");

/**
 * 请求被取消时抛出`Cancel`
 */
function throwIfCancellationRequested(config) {
  if (config.cancelToken) {
    config.cancelToken.throwIfRequested();
  }
}

/**
 * 使用配置的适配器向服务器发送一个请求
 *
 * @param {object} config 这个配置将被使用于当前请求
 * @returns {Promise} 这个Promise将转换为完成态
 */
module.exports = function dispatchRequest(config) {
  throwIfCancellationRequested(config);

  // 确保请求头存在
  config.headers = config.headers || {};

  // 转换请求数据
  config.data = transformData(
    config.data,
    config.headers,
    config.transformRequest
  );

  // 合并请求头
  config.headers = utils.merge(
    config.headers.common || {},
    config.headers[config.method] || {},
    config.headers
  );

  // 移除请求头中的请求方法
  utils.forEach(
    ["delete", "get", "head", "post", "put", "patch", "common"],
    function cleanHeaderConfig(method) {
      delete config.headers[method];
    }
  );

  const adapter = config.adapter || defaults.adapter;

  return adapter(config).then(
    function onAdapterResolution(response) {
      throwIfCancellationRequested(config);

      // 转换响应数据
      response.data = transformData(
        response.data,
        response.headers,
        config.transformResponse
      );

      return response;
    },
    function onAdapterRejection(reason) {
      if (!isCancel(reason)) {
        throwIfCancellationRequested(config);

        // 转换响应数据
        if (reason && reason.response) {
          reason.response.data = transformData(
            reason.response.data,
            reason.response.headers,
            config.transformResponse
          );
        }
      }

      return Promise.reject(reason);
    }
  );
};
